Set-StrictMode -Version 2.0

function global:New-Certificate (
                          [parameter(Mandatory=$true)]
                          [String]
                          $certificatePath,
                          [parameter(Mandatory=$true)]
                          [String]
                          $commonName,
                          [Switch]
                          $NotExportable
                         )
{
<#
.Description
   Creates a new certificate, by calling makecert on your behalf.

   Right now MakeCert is distributed with this module, it is available for free in the windows SDK @
   http://go.microsoft.com/fwlink/?LinkID=150217

   Once you've installed the Windows SDK you'll find makecert here: 
   C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin>

.Example 
    C:\PS> New-Certificate cert:\CurrentUser\My CertificateHelper

        Directory: Microsoft.PowerShell.Security\Certificate::CurrentUser\My


    Thumbprint                                Subject
    ----------                                -------
    0CD5521A191C5CB77973487E519B898948C4B395  CN=CertificateHelper

#>
    $certStore = gi $certificatePath
    if (-not $certStore -or $certStore.GetType() -ne  [System.Security.Cryptography.X509Certificates.X509Store])
    {
        throw "$certificatePath must be a certificate store"
    }

    $store = split-path $certStore.PSPath -leaf
    $location = ((split-path $certStore.PSPath) -split "::")[1]


    $x509Name = "CN="+$commonName
    # makcert will re-use a key container.
    $keyname = $x509Name+[Guid]::NewGuid().ToString()

    $makeCertArgs =  " -sk $keyname -ss $store -sr $location -n $x509Name"
    if (-not $NotExportable) 
    {
        $makeCertArgs = " -pe " + $makeCertArgs;
    }

    $output = & "$psScriptRoot\makecert.exe" $makeCertArgs.split()
    if ($output -ne "Succeeded")
    {
        throw "MakeCert Failed with error $output`r[$makeCertArgs]"
    }

    # We want to return a certificate, but makecert doesn't. We need to find the newly created cert.
    # Luckily we know the name of the key contianer (which contains a GUID). We'll  Search for and return that :) 
    # Unfortunatly, accessing a pivate key access may prompt us to insert a private key, so only access private keys where we have a matching subject name.
    # (It's possible we'd *still* get a smartcard prompt if we had a cert with the same subject name, with a private key backed by a smartcard - but very unlikely)
    
    $theNewCert = dir $certificatePath | ? {$_.subject -eq $x509Name }| ? {$_.PrivateKey.CspKeyContainerInfo.KeyContainerName -eq $keyname}
    return $theNewCert
}

function global:Remove-Certificate(
        [parameter(
            Mandatory=$true
         )]
        $certificatePath)
{
<#
.Description
    Remove-Certificate erases a certificate from the Certificate Store. Erasing the certificate does not effect the private key the certificate may link to.

.Example 
dir cert:\CurrentUser\My | ? {$_.Subject -eq "CN=CertificateHelper"}

    Directory: Microsoft.PowerShell.Security\Certificate::CurrentUser\My


Thumbprint                                Subject
----------                                -------
0CD5521A191C5CB77973487E519B898948C4B395  CN=CertificateHelper

C:\PS> Remove-Certificate cert:\CurrentUser\My\CE95F9CCCC6461A667A56C272A633F441C5A9E3D    
C:\PS> dir cert:\CurrentUser\My | ? {$_.Subject -eq "CN=CertificateHelper"}
C:\PS>
#>
    $cert = gi $certificatePath
    if (-not $cert -or $cert.GetType() -ne  [System.Security.Cryptography.X509Certificates.X509Certificate2])
    {
        throw  "$certificatePath must be a certificate in the certificate store"
    }

    $certStore = gi (Split-Path $cert.PSPath) 
    $certStore.Open("ReadWrite")
    $certStore.Remove($cert)
    $certStore.Close()
    #done
}

